#include <iostream>
#include <conio.h>
#include <windows.h>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <fstream>
using namespace std;

// 全局常量与变量
const int WIDTH = 40;
const int HEIGHT = 20;
int score = 0, highScore = 0;
int sleepTime = 200; // 控制游戏速度（初始200ms）
enum Direction { STOP = 0, UP, DOWN, LEFT, RIGHT };
Direction dir;
bool gameOver = false;
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);

// 蛇身结构体
struct SnakeSegment {
    int x, y;
};
vector<SnakeSegment> snake;
int foodX, foodY;

// 函数声明
void HideCursor();
void SetColor(int color);
void DrawBorder();
void InitSnake();
void GenerateFood();
void MoveSnake();
void Input();
void CheckCollision();
void ShowScore();
void SaveScore();
void LoadScore();
void GameOverScreen();
void WelcomeScreen();
void ShowHelp();

void speedup();   // 加速函数
void slowdown();  // 减速函数

// 隐藏控制台光标
void HideCursor() {
    CONSOLE_CURSOR_INFO cursorInfo;
    cursorInfo.bVisible = false;
    cursorInfo.dwSize = 1;
    SetConsoleCursorInfo(hOut, &cursorInfo);
}

// 设置控制台颜色
void SetColor(int color) {
    SetConsoleTextAttribute(hOut, color);
}

// 绘制游戏边框
void DrawBorder() {
    SetColor(3); // 青色边框
    for (int i = 0; i < HEIGHT; i++) {
        for (int j = 0; j < WIDTH; j++) {
            if (i == 0 || i == HEIGHT - 1 || j == 0 || j == WIDTH - 1) {
                cout << "#";
            }
            else {
                cout << " ";
            }
        }
        cout << endl;
    }
}

// 初始化蛇
void InitSnake() {
    snake.clear();
    snake.push_back({ WIDTH / 2, HEIGHT / 2 }); // 蛇头
    snake.push_back({ WIDTH / 2 - 1, HEIGHT / 2 });
    snake.push_back({ WIDTH / 2 - 2, HEIGHT / 2 });
}

// 生成食物
void GenerateFood() {
    bool valid;
    do {
        valid = true;
        foodX = rand() % (WIDTH - 4) + 2;
        foodY = rand() % (HEIGHT - 4) + 2;

        // 检查食物是否生成在蛇身上
        for (auto& segment : snake) {
            if (foodX == segment.x && foodY == segment.y) {
                valid = false;
                break;
            }
        }
    } while (!valid);

    SetColor(12); // 红色食物
    COORD pos = { foodX, foodY };
    SetConsoleCursorPosition(hOut, pos);
    cout << "●";
}

// 移动蛇
void MoveSnake() {
    // 保存旧尾部坐标
    int prevTailX = snake.back().x;
    int prevTailY = snake.back().y;

    // 移动身体
    for (int i = snake.size() - 1; i > 0; i--) {
        snake[i] = snake[i - 1];
    }

    // 移动头部
    switch (dir) {
    case UP:    snake[0].y--; break;
    case DOWN:  snake[0].y++; break;
    case LEFT:  snake[0].x--; break;
    case RIGHT: snake[0].x++; break;
    }

    // 绘制新头部
    SetColor(10); // 绿色头部
    COORD headPos = { snake[0].x, snake[0].y };
    SetConsoleCursorPosition(hOut, headPos);
    cout << "■";

    // 如果吃到食物
    if (snake[0].x == foodX && snake[0].y == foodY) {
        snake.push_back({ prevTailX, prevTailY });

        // 根据当前速度计算得分
        if (sleepTime <= 100)
            score += 12;
        else if (sleepTime <= 200)
            score += 10;
        else
            score += 8;

        // 自动加速
        if (sleepTime > 50) {
            sleepTime -= 10;
            if (sleepTime < 50) sleepTime = 50;
        }

        GenerateFood();
    }
    else { // 清除旧尾部
        COORD tailPos = { prevTailX, prevTailY };
        SetConsoleCursorPosition(hOut, tailPos);
        cout << " ";
    }
}

// 键盘输入处理
void Input() {
    if (_kbhit()) {
        char key = _getch();
        if (key == 0xE0 || key == 0x00) { // 扩展键或F键
            key = _getch(); // 获取实际键码
            switch (key) {
            case 72: if (dir != DOWN) dir = UP; break;    // 上箭头
            case 80: if (dir != UP) dir = DOWN; break;    // 下箭头
            case 75: if (dir != RIGHT) dir = LEFT; break; // 左箭头
            case 77: if (dir != LEFT) dir = RIGHT; break; // 右箭头
            case 59: // F1 (加速)
                speedup();
                break;
            case 60: // F2 (减速)
                slowdown();
                break;
            }
        }
        else {
            switch (key) {
            case 27: gameOver = true; break;              // ESC键
            case 'w': if (dir != DOWN) dir = UP; break;
            case 's': if (dir != UP) dir = DOWN; break;
            case 'a': if (dir != RIGHT) dir = LEFT; break;
            case 'd': if (dir != LEFT) dir = RIGHT; break;
            }
        }
    }
}

// 碰撞检测
void CheckCollision() {
    // 撞墙检测
    if (snake[0].x <= 0 || snake[0].x >= WIDTH - 1 ||
        snake[0].y <= 0 || snake[0].y >= HEIGHT - 1) {
        gameOver = true;
    }

    // 自噬检测
    for (int i = 1; i < snake.size(); i++) {
        if (snake[0].x == snake[i].x && snake[0].y == snake[i].y) {
            gameOver = true;
            break;
        }
    }
}

// 显示分数
void ShowScore() {
    COORD pos = { WIDTH + 5, 2 };
    SetConsoleCursorPosition(hOut, pos);
    SetColor(14); // 黄色
    cout << "当前得分: " << score;

    pos.Y = 4;
    SetConsoleCursorPosition(hOut, pos);
    cout << "最高记录: " << highScore;

    pos.Y = 6;
    SetConsoleCursorPosition(hOut, pos);
    int speedLevel = (300 - sleepTime) * 10 / (300 - 50); // 计算速度等级 0~10
    cout << "当前速度: " << speedLevel << "/10"; // 速度等级显示
}

// 保存分数
void SaveScore() {
    ofstream outFile("save.txt");
    if (outFile) {
        outFile << highScore;
        outFile.close();
    }
}

// 读取分数
void LoadScore() {
    ifstream inFile("save.txt");
    if (inFile) {
        inFile >> highScore;
        inFile.close();
    }
}

// 游戏结束界面
void GameOverScreen() {
    system("cls");
    SetColor(12);
    cout << "\n\n\t游戏结束！\n\n";
    SetColor(15);

    if (score > highScore) {
        highScore = score;
        SaveScore();
        cout << "\t★ 新纪录诞生！ ★\n";
    }

    cout << "\t最终得分: " << score << endl;
    cout << "\t最高记录: " << highScore << endl;

    cout << "\n\t1. 重新开始\n\t2. 退出游戏\n";
    char choice = _getch();
    if (choice == '1') {
        score = 0;
        gameOver = false;
        dir = RIGHT;
        sleepTime = 200; // 重置速度
        InitSnake();
        system("cls");
        DrawBorder();
        // 重新绘制蛇身
        SetColor(10);
        for (auto& segment : snake) {
            COORD pos = { segment.x, segment.y };
            SetConsoleCursorPosition(hOut, pos);
            cout << "■";
        }
        GenerateFood();
        ShowScore();
    }
    else {
        exit(0);
    }
}

// 欢迎界面
void WelcomeScreen() {
    system("cls");
    SetColor(10);
    cout << R"(
        ██████╗  █████╗ ███╗   ██╗███████╗
        ██╔══██╗██╔══██╗████╗  ██║██╔════╝
        ██████╔╝███████║██╔██╗ ██║█████╗  
        ██╔═══╝ ██╔══██║██║╚██╗██║██╔══╝  
        ██║     ██║  ██║██║ ╚████║███████╗
        ╚═╝     ╚═╝  ╚═╝╚═╝  ╚═══╝╚══════╝
    )" << endl;

    SetColor(11);
    cout << "\n\t1. 开始游戏\n\t2. 游戏说明\n\t3. 退出游戏\n";

    char choice;
    do {
        choice = _getch();
    } while (choice < '1' || choice > '3');

    switch (choice) {
    case '1':
        system("cls");
        dir = RIGHT;
        DrawBorder();
        InitSnake();
        // 绘制初始蛇身
        SetColor(10);
        for (auto& segment : snake) {
            COORD pos = { segment.x, segment.y };
            SetConsoleCursorPosition(hOut, pos);
            cout << "■";
        }
        GenerateFood();
        ShowScore();
        break;
    case '2':
        ShowHelp();
        WelcomeScreen();
        break;
    case '3':
        exit(0);
    }
}

// 游戏说明
void ShowHelp() {
    system("cls");
    SetColor(14);
    cout << "\n\t=== 游戏说明 ===";
    SetColor(11);
    cout << R"(
    使用方向键或WASD控制蛇的移动
    吃掉红色食物(●)可以使蛇变长
    撞到墙壁或自己身体会导致游戏结束
    按ESC键可以随时退出游戏
    按F1加速，F2减速
    )";
    SetColor(15);
    cout << "\n\t按任意键返回主菜单...";
    _getch();
}

// 加速函数
void speedup() {
    if (sleepTime > 50) {
        sleepTime -= 20;
        if (sleepTime < 50) sleepTime = 50;
    }
}

// 减速函数
void slowdown() {
    if (sleepTime < 300) {
        sleepTime += 20;
        if (sleepTime > 300) sleepTime = 300;
    }
}

int main() {
    srand(time(0));  // 初始化随机种子
    HideCursor();
    LoadScore();

    while (true) {
        WelcomeScreen();
        while (!gameOver) {
            MoveSnake();
            CheckCollision();
            Input();
            ShowScore();
            Sleep(sleepTime); // 使用动态速度
        }
        GameOverScreen();
    }

    return 0;
}